package com.personal.validate.impl;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.personal.core.bean.TwoTuple;
import com.personal.core.utils.CoreUtil;
import com.personal.core.utils.ReGularUtil;
import com.personal.core.utils.StringUtil;
import com.personal.validate.consts.LanguageTypeEnum;
import com.personal.validate.port.Validation;

/**
 * 校验实现基础类
 * @author cuibo
 *
 */
public abstract class BaseValidation implements Validation
{
    /** 校验语句 */
    protected String validationInfo;

    /** 待校验的值 */
    protected Map<String, Object> validationValue;

    protected static final String 英文右括号 = ")";
    protected static final String 中文右括号 = "）";
    protected static final String 英文左括号 = "(";
    protected static final String 中文左括号 = "（";

    public BaseValidation()
    {

    }

    /**
     * @param validationInfo   校验语句
     * @param validationValue  待校验的值
     */
    public BaseValidation(String validationInfo, Map<String, Object> validationValue)
    {
        super();
        this.validationInfo = validationInfo;
        this.validationValue = validationValue;
    }

    @Override
    public List<ValidationResult> getAllValidationResult() throws Exception
    {
        return getAllValidationResult(null);
    }

    @Override
    public ValidationResult getValidationResult() throws Exception
    {
        return getValidationResult(null);
    }

    /**
     * 获取指标值
     * @param targetName
     * @return
     */
    public String getTargetValue(String targetName)
    {
        if (validationValue != null && validationValue.size() > 0)
        {
            return CoreUtil.parseStr(validationValue.get(targetName));
        }
        return null;
    }

    public String getValidationInfo()
    {
        return validationInfo;
    }

    public Map<String, Object> getValidationValue()
    {
        return validationValue;
    }

    @Override
    public void setValidationInfo(String validationInfo)
    {
        this.validationInfo = validationInfo;
    }

    @Override
    public void setValidationValue(Map<String, Object> validationValue)
    {
        this.validationValue = validationValue;
    }

    @Override
    public void languageChange(LanguageTypeEnum source, LanguageTypeEnum target)
    {
        Map<String, String> relMap = getLanguageChangeRelMap(source, target);
        if (!CoreUtil.isEmpty(relMap))
        {
            // 统一处理中引文括号
            switch (source)
            {
            case 中文:
                switch (target)
                {
                case 英文:
                    relMap.put(中文左括号, 英文左括号);
                    relMap.put(中文右括号, 英文右括号);
                    break;
                default:
                    break;
                }
                break;
            case 英文:
                switch (target)
                {
                case 中文:
                    relMap.put(英文左括号, 中文左括号);
                    relMap.put(英文右括号, 中文右括号);
                    break;
                default:
                    break;
                }
                break;

            default:
                break;
            }
            for (Entry<String, String> entry : relMap.entrySet())
            {
                validationInfo = StringUtil.replace(validationInfo, entry.getKey(), entry.getValue());
            }
        }
    }

    /**
     * 获取语言切换的映射关系
     * @param source
     * @param target
     * @return
     */
    protected abstract Map<String, String> getLanguageChangeRelMap(LanguageTypeEnum source, LanguageTypeEnum target);

    /**
     * 批量计算表达式
     * 返回结果的数组大小和传入的数组大小一定一致
     * @param exps
     * @return
     */
    protected Object[] calculateExp(String... exps)
    {
        // cb 2017 04 20 直接使用
        // cb 2017 04 20 直接使用
        if (exps == null || exps.length == 0)
        {
            return null;
        }
        Object[] result = new Object[exps.length];
        int index = 0;
        for (String string : exps)
        {
            if (CoreUtil.isEmpty(string))
            {
                result[index++] = string;
                continue;
            }
            // 优化顺序
            if (validationValue.containsKey(string))
            {
                result[index++] = validationValue.get(string);
            } else
            {
                // 判断是否是表达式，并且忽略时间格式的影响
                if (CoreUtil.checkIsExp(string)
                        && !(ReGularUtil.ISDATE.matcher(string).matches() && CoreUtil.parseDate(string) != null))
                {
                    result[index++] = CoreUtil.calculateExByAvi(string, validationValue);
                } else
                {
                    result[index++] = string;
                }
            }

        }
        return result;
        //        // 计算结果
        //        TwoTuple<Boolean, Object[]> result = replaceTargetNameWithZero(exps);
        //        if (result == null)
        //        {
        //            return null;
        //        }
        //        Object[] arr = result.getB();
        //        if (arr == null)
        //        {
        //            return null;
        //        }
        //        int index = 0;
        //        String string = "";
        //        for (Object obj : arr)
        //        {
        //            string = CoreUtil.parseStr(obj);
        //            // cb2017 04 18 时间格式本身里面就带有运算符号
        //            if (string != null
        //                    && (string.contains("+") || string.contains("-") || string.contains("*") || string.contains("/"))
        //                    && result.getA())
        //            {
        //                arr[index] = CoreUtil.calculateEx(string);
        //            } else
        //            {
        //                arr[index] = obj;
        //            }
        //            index++;
        //        }
        //        return arr;
    }

    protected void checkCanValidate()
    {
        checkCanValidate(false);
    }

    /**
     * 
     * @param replaceKH 是否去除前后括号
     */
    protected void checkCanValidate(boolean replaceKH)
    {
        if (CoreUtil.isEmpty(validationInfo) || validationValue == null)
        {
            throw new RuntimeException("校验语句或者校验值为空，校验失败！");
        }
        // 去除所有空格
        validationInfo = ReGularUtil.NULLPATTERN.matcher(validationInfo).replaceAll("");
        if (replaceKH)
        {
            if (validationInfo.startsWith("("))
            {
                validationInfo = validationInfo.substring(1);
            }
            if (validationInfo.endsWith(")"))
            {
                validationInfo = validationInfo.substring(0, validationInfo.length() - 1);
            }
        }
    }

    /**
     * 批量替换表达式，将指标名用其值替换
     * 返回结果的数组大小和传入的数组大小一定一致
     * @param exps
     * @return
     */
    protected String[] replaceTargetName(String... exps)
    {
        if (exps == null || exps.length == 0)
        {
            return null;
        }
        String[] arr = new String[exps.length];
        int index = 0;
        for (String string : exps)
        {
            arr[index] = string;
            index++;
        }
        if (validationValue != null && validationValue.size() > 0)
        {
            index = 0;
            for (String string : arr)
            {
                for (Entry<String, Object> entry : validationValue.entrySet())
                {
                    // 优化性能，不包含就直接跳过
                    if (!string.contains(entry.getKey()))
                    {
                        continue;
                    }
                    string = StringUtil.replace(string, entry.getKey(), CoreUtil.isEmpty(entry.getValue()) ? ""
                            : CoreUtil.parseStr(entry.getValue()));
                }
                arr[index] = string;
                index++;
            }
        }
        return arr;
    }

    /**
     * 批量替换表达式，将指标名用其值替换,空的时候填充0
     * 返回结果的数组大小和传入的数组大小一定一致
     * @param exps
     * @return
     */
    protected TwoTuple<Boolean, Object[]> replaceTargetNameWithZero(String... exps)
    {
        if (exps == null || exps.length == 0)
        {
            return null;
        }
        TwoTuple<Boolean, Object[]> result = new TwoTuple<Boolean, Object[]>();
        String[] arr = new String[exps.length];
        // 结果
        Object[] resultObj = new Object[exps.length];
        int index = 0;
        for (String string : exps)
        {
            arr[index] = string;
            index++;
        }
        boolean isExp = false;
        if (validationValue != null && validationValue.size() > 0)
        {
            index = 0;
            sign: for (String string : arr)
            {
                if (CoreUtil.isEmpty(string))
                {
                    resultObj[index++] = string;
                    continue;
                }
                for (Entry<String, Object> entry : validationValue.entrySet())
                {
                    // 优化性能，不包含就直接跳过
                    if (!string.contains(entry.getKey()))
                    {
                        continue;
                    }
                    // 为了防止字串替换出错，应在替换之前校验
                    if (string.matches(".*[\\+\\-\\*\\/\\(]" + entry.getKey() + ".*")
                            || string.matches(".*" + entry.getKey() + "[\\+\\-\\*\\/\\)].*"))
                    {
                        isExp = true;
                        string = StringUtil.replace(string, entry.getKey(), CoreUtil.isEmpty(entry.getValue()) ? "0"
                                : CoreUtil.parseStr(entry.getValue()));
                    } else if (string.equals(entry.getKey()))
                    {
                        // 考虑 string 中只有一个key的
                        resultObj[index++] = entry.getValue();
                        continue sign;
                    }
                }
                resultObj[index++] = string;
            }
        }
        result.setB(resultObj);
        result.setA(isExp);
        return result;
    }

}
